#ifndef INIPARSER_H
#define INIPARSER_H

#include <stdio.h>
#include <string>
#include <list>

class FIni
{
public:
    enum eElemType
    {
        Whiteline,
        Comment,
        Flag,
        NameValuePair,
    };

    enum eAction
    {
        KeepUnchanged,
        Added,
        Removed,  // not used yet
        Changed,
    };

    struct Elem
    {
        eElemType type;
        std::string name;
        std::string value;
        eAction action;
    };

public:
    FIni();
    virtual ~FIni();

    bool parse(const std::string& file);

    template<typename T, typename Ansi2T>
    T get(const std::string& name, const T& default_value, Ansi2T functor) const;

    std::string get(const std::string& name, const std::string& default_value = "") const;
    float get(const std::string& name, const float default_value = 0.0f) const;
    int get(const std::string& name, const int default_value = 0) const;

    void set(const std::string& name, const std::string& value, bool reading = false);
    void setFlag(const std::string& name, bool reading = false);
    void remove(const std::string& name);
    bool isExist(const std::string& name) const;

    void flush();

    void dump(FILE* pFile = stdout);

private:
    void init();

private:
    std::list<Elem> m_content;
    std::string m_filePath;
    FILE* m_pFile;
};

template<typename T, typename Ansi2T>
T FIni::get(const std::string& name, const T& default_value, Ansi2T functor) const
{
    for (auto iter = m_content.begin(); iter != m_content.end(); iter++)
    {
        if (iter->type == NameValuePair && iter->name == name)
        {
            return functor(iter->value.c_str());
        }
    }

    return default_value;
}

#endif //INIPARSER_H
